
package control;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JPanel;
import modelos.Dato;
import modelos.DatosBarras;
import modelos.DatosFuncion;
import modelos.DatosPie;

/**
 * Dibuja en el lienzo la grafica definida por el constructor
 * @author Rafael Carrillo 90465
 */
public class Grafica {
    
    private int tipo;
    private JPanel lienzo;
    private final Color[] colores = {Color.red, Color.green, Color.blue,Color.magenta
           ,Color.ORANGE,Color.gray};
    
   private DatosBarras barras;
   private DatosFuncion funcion;
   private DatosPie pie;
   
   /**
    * Inicializa los atributos necesarios para dibujar una grafica de barras
    * @param tipo Tipo de grafica a dibujar
    * @param lienzo Lienzo donde se va a dibujar
    * @param barras Modelo de la grafica de Barras
    */
    public Grafica(int tipo, JPanel lienzo, DatosBarras barras) {
        this.tipo = tipo;
        this.lienzo = lienzo;
        this.barras = barras;
    }
    /**
     * Inicializa los atributos necesarios para dibujar una grafica de  funcion
     * @param tipo Tipo de grafica a dibujar
     * @param lienzo Lienzo donde se va a dibujar
     * @param funcion Modelo de la grafica de funcion
     */
    public Grafica(int tipo, JPanel lienzo, DatosFuncion funcion) {
        this.tipo = tipo;
        this.lienzo = lienzo;
        this.funcion = funcion;
    }

    /**
     * Inicializa los atributos necesarios para dibujar una grafica de pie
     * @param tipo Tipo de grafica a dibujar
     * @param lienzo Lienzo donde se va a dibujar
     * @param pie  Modelo de la grafica de pie
     */
    public Grafica(int tipo, JPanel lienzo, DatosPie pie) {
        this.tipo = tipo;
        this.lienzo = lienzo;
        this.pie = pie;
    }
    
    
    
    /**
     * Dibuja la gráfica de barras con los datos generados en el objeto de tipo
     * DatosBarras
     */
    protected void graficaBarras(){
        Graphics g=lienzo.getGraphics();
        Graphics2D g2=(Graphics2D)g;
        Dimension d=lienzo.getSize();
        lienzo.paint(g);
        Font font=new Font("Serif",Font.BOLD,15);
        g2.setFont(font);
        String titulo=barras.getTitulo();
        int stringWidth=g2.getFontMetrics().stringWidth(titulo);
        int stringHeight=g2.getFontMetrics().getHeight();
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        g2.drawString(barras.getTitulo(),(d.width/2)-(stringWidth/2),g2.getFontMetrics().getHeight());
        
        //EjeY
        Line2D eje=new Line2D.Double(0.05*d.width,0.95*d.height,0.05*d.width ,-d.height*.9);
        g2.draw(eje);
        double separacion=(d.height)/10;
        double recorrido=0;
        
        //Divisiones
        for(int i=0;i<10;i++){          
            eje=new Line2D.Double(0.05*d.width,recorrido+separacion,d.width,recorrido+separacion);
            g2.draw(eje);
            recorrido+=separacion;
        }
        
        AffineTransform orig = g2.getTransform();
        g2.translate(stringHeight,d.height/2);
        g2.rotate(-Math.PI/2);
        g2.drawString(barras.getTituloY(),0,0);     
        g2.setTransform(orig);     
        
        //EjeX
        eje=new Line2D.Double(0.05*d.width,0.95*d.height,d.width,0.95*d.height);
        g2.draw(eje);
        g2.translate(d.width/2, d.height);
        g2.drawString(barras.getTituloX(), 0,0);
        g2.setTransform(orig);
        
        //Dibuja Grafica
        int numeroBarras=barras.getNumDatos();
        
        double x=0.05*d.width;
        Dato[] datos=barras.getDatos();
        final double paso=((d.width-x)/numeroBarras);
        for(int i=0;i<numeroBarras;i++){
            g2.setPaint(colores[i%colores.length]);
            double alto=datos[i].valor;
            Font fBarras=new Font("Serif", Font.PLAIN, 15);
            g2.setFont(fBarras);            
            Rectangle2D barra=new Rectangle2D.Double(x,(d.height-alto),paso,alto);
            g2.fill(barra);            
            g2.draw(barra);
            g2.setColor(Color.BLACK);
            
            //dibuja rotulos de las barras
            orig = g2.getTransform();
            g2.translate((float)x+30+stringHeight,(float)d.height-(alto/2));
            g2.rotate(-Math.PI/2);
            g2.drawString(datos[i].titulo,0,0);
            g2.setTransform(orig);
            x+=paso;
        } 
        
        
    }
    /**
     * Dibuja la gráfica de pie con los datos generados en el objeto de tipo
     * DatosPie
     */
    protected void graficaPie(){
        Graphics g=lienzo.getGraphics();
        Graphics2D g2=(Graphics2D)g;
        Dimension d=lienzo.getSize();
        lienzo.paint(g);        
        double ancho=(d.height/1.5);
        double alto=(d.height/1.5);
        double x=(d.width/2)-ancho; //Coordenada x al origen del circulo
        double y=(d.height/2)/2; //Coordenada y al origen del circulo
        Dato[]valores=pie.getDatos();
        double last=0;
        Font original=g2.getFont();
        Font titulo=new Font("Serif",Font.PLAIN,20);
        g2.setFont(titulo);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        //Dibuja Titulo de la Gráfica
        g2.drawString(pie.getTitulo(),(d.width/2)-(g2.getFontMetrics().stringWidth(pie.getTitulo()) /2),g2.getFontMetrics().getHeight());
        g2.setFont(original);
        AffineTransform orig=new AffineTransform(g2.getTransform());
        
        for(int i=0;i<pie.getNumDatos();i++){
            g2.setPaint(colores[i%colores.length]);
            double endDegree=(valores[i].valor*360);
            Arc2D arcos=new Arc2D.Double(x, y,ancho,alto,last,endDegree,Arc2D.PIE);
            g2.fill(arcos);
            g2.draw(arcos);   
            //Dibujar su Rotulo en la parte derecha
            Rectangle2D vineta=new Rectangle2D.Double(d.width*.6,(d.height*.3)+(i*30),30,30);
            g2.fill(vineta);
            g2.drawString(valores[i].titulo,(float)(d.width*.6)+40,(float)(d.height*.3)+(i*30)+15);
            g2.setTransform(orig);
            //Dibujar titulos en la grafica         
            g2.translate(x+(ancho/2), y+(alto/2));
            double rad=((last+endDegree+last)/2*(Math.PI/180));
            last+=endDegree;
            g2.rotate(-rad);
            g2.setColor(Color.BLACK);
            int porcentaje=(int)(valores[i].valor*100);
            String rotulo=porcentaje+"%";
            int posRotulo=75-(g2.getFontMetrics().stringWidth(rotulo)/2);//Numeros magicos FTW
            g2.drawString(rotulo,posRotulo ,0);
            g2.setTransform(orig);
            
            
            
            
        }      
    }
    
    
    /**
     * Dibuja la gráfica de funcion (Dispersion) con los datos generados en el objeto de tipo
     * Lo hice como grafica de dispersion porque no pude visualizar como debia dibujarse la grafica
     */
    protected void graficaFuncion(){
        Graphics g=lienzo.getGraphics();
        Graphics2D g2=(Graphics2D)g;
        Dimension d= lienzo.getSize();
        lienzo.paint(g);
        double maxY=funcion.getMaxY();
        double escX=0.9*d.width/(funcion.getMaxX()-funcion.getMinX());
        double escY=0.9*d.height/(funcion.getMaxY()-funcion.getMinY());
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        //Dibuja Titulo de la Grafica
        Font fuenteOriginal=g2.getFont();
        Font titulo=new Font("Serif",Font.PLAIN,20);
        g2.setFont(titulo);
        //Dibuja Titulo de la Gráfica
        g2.drawString(funcion.getTitulo(),(d.width/2)-(g2.getFontMetrics().stringWidth(funcion.getTitulo()) /2),g2.getFontMetrics().getHeight());
        
        //Dibuja Titulo Eje Y
        
         //EjeY
        Line2D eje=new Line2D.Double(0.05*d.width,d.height-(0.05*d.height),0.05*d.width ,escY);
        g2.draw(eje);
        double separacionY=(d.height-(0.05*d.height))/10;
        double recorrido=0;
        double separacionX=(d.width-(0.05*d.width))/10;
        
        //Divisiones EjeY
        for(int i=0;i<10;i++){          
            eje= new Line2D.Double(0.05*d.width,recorrido+separacionY,d.width,recorrido+separacionY);
            g2.draw(eje);
            recorrido+=separacionY;
        }
        //Eje X
        eje=new Line2D.Double(0.05*d.width,d.height-(0.05*d.height),d.width,d.height-(0.05*d.height));
        g2.draw(eje);
        
        //Divisiones ejeX
        recorrido=d.width*0.05;
        for(int i=0;i<10;i++){          
            eje=new Line2D.Double(recorrido,d.height-(0.05*d.height),recorrido,0);
            g2.draw(eje);
            recorrido+=separacionX;
        }        
 
        
        AffineTransform orig=new AffineTransform(g2.getTransform());
        g2.translate(20, d.height/2);
        g2.rotate(-Math.PI/2);
        g2.drawString(funcion.getTituloY(), 0, 0);
        g2.setTransform(orig);
        //Dibuja Titulo Eje X
        g2.translate(d.width/2, d.height);
        g2.drawString(funcion.getTituloX(), 0, 0);
        g2.setFont(fuenteOriginal);
        g2.setTransform(orig);
        //Dibuja Grafico
        Line2D grafico=new Line2D.Double(funcion.getMinX(),
                d.height-funcion.getMinY(), funcion.getMaxX(),d.height-maxY+50);
        g2.draw(grafico);
        double[][] puntos=funcion.getPuntos();        
        for(int i=0;i<funcion.getNumPuntos();i++){
            g2.setPaint(colores[i%colores.length]);
            double y=d.height-puntos[i][1];
            if(puntos[i][1]==maxY)    
                y=y+50;
            double x=puntos[i][0]-2.5;
            Rectangle2D punto=new Rectangle2D.Double(x,y,5,5);          
            g2.fill(punto);
            g2.draw(punto);
        }
    }
    
}
